#include "singleinstancechecker.h"

SingleInstanceChecker::SingleInstanceChecker(const QString &serverName,
                                             QWidget *mainWindow,
                                             QObject *parent)
    : QObject(parent)
    , m_serverName(serverName)
    , m_localServer(nullptr)
    , m_mainWindow(mainWindow)
{
    if (isAnotherInstanceRunning()) {
        sendBringToFrontMessage();
        return;
    }
    m_localServer = createLocalServer();
    if (m_localServer) {
        connect(m_localServer,
                &QLocalServer::newConnection,
                this,
                &SingleInstanceChecker::handleNewConnection);
    }
}

SingleInstanceChecker::~SingleInstanceChecker()
{
    if (m_localServer) {
        m_localServer->close();
        delete m_localServer;
    }
}

bool SingleInstanceChecker::isAnotherInstanceRunning()
{
    QLocalSocket socket;
    socket.connectToServer(m_serverName);
    if (socket.waitForConnected(500)) {
        qDebug() << "Another instance is already running.";
        return true;
    }
    return false;
}

bool SingleInstanceChecker::isSingleInstance() const
{
    return m_localServer != nullptr;
}

QLocalServer *SingleInstanceChecker::createLocalServer()
{
    QLocalServer::removeServer(m_serverName);
    QLocalServer *server = new QLocalServer(this);
    if (!server->listen(m_serverName)) {
        qDebug() << "Failed to start local server:" << server->errorString();
        delete server;
        return nullptr;
    }
    return server;
}

void SingleInstanceChecker::sendBringToFrontMessage()
{
    QLocalSocket socket;
    socket.connectToServer(m_serverName);
    if (socket.waitForConnected(500)) {
        socket.write("BringToFront");
        socket.waitForBytesWritten();
        socket.close();
    }
}

void SingleInstanceChecker::handleNewConnection()
{
    QLocalSocket *socket = m_localServer->nextPendingConnection();
    if (socket) {
        connect(socket, &QLocalSocket::readyRead, [this, socket]() {
            QByteArray data = socket->readAll();
            if (data == "BringToFront") {
                if (m_mainWindow) {
                    m_mainWindow->show();
                    m_mainWindow->raise();
                    m_mainWindow->activateWindow();
                }
            }
            socket->close();
            socket->deleteLater();
        });
    }
}
